home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / UUPC11QS.ARJ / IMPORT.C < prev    next >
C/C++ Source or Header  |  1991-11-21  |  21KB  |  456 lines

  1. /*--------------------------------------------------------------------*/
  2. /*    i m p o r t . c                                                 */
  3. /*                                                                    */
  4. /*    File name mapping routines for UUPC/extended                    */
  5. /*--------------------------------------------------------------------*/
  6.  
  7. #include <stdio.h>
  8. #include <ctype.h>
  9. #include <string.h>
  10. #include <time.h>
  11.  
  12. #include "lib.h"
  13. #include "import.h"
  14. #include "arbmath.h"
  15. #include "hostable.h"
  16. #include "usertabl.h"
  17. #include "security.h"
  18.  
  19. #define MAX_DIGITS 20         /* Number of digits for arb math */
  20.  
  21. /*--------------------------------------------------------------------*/
  22. /*                    Internal function prototypes                    */
  23. /*--------------------------------------------------------------------*/
  24.  
  25. static boolean ValidDOSName( const char *s);
  26.  
  27. #define min(x,y) (((x) < (y)) ? (x) : (y))
  28.  
  29. currentfile();
  30.  
  31. /*-------------------------------------------------------------------*/
  32. /*                                                                   */
  33. /*   i m p o r t p a t h                                             */
  34. /*                                                                   */
  35. /*   Convert a canonical name to a format the host can handle        */
  36. /*                                                                   */
  37. /*   These routines convert file name between canonical form, which  */
  38. /*   is defined as a 'unix' style pathname, and the MS-DOS all       */
  39. /*   uppercase "xxxxxxxx.xxx" format.                                */
  40. /*                                                                   */
  41. /*   If the canonical name does not have a path, that is the file is */
  42. /*   destined for the local spool directory, we can assume the UNIX  */
  43. /*   name will normally be in a format like this:                    */
  44. /*                                                                   */
  45. /*                                                                   */
  46. /*       X.hostid#######            (Execute files)                  */
  47. /*       C.hostid#######            (Call files)                     */
  48. /*       D.hostid#######            (Data files)                     */
  49. /*                                                                   */
  50. /*   where "hostid" may be most, but not always all, of the local    */
  51. /*   host or remote host (the file came from or is going to) and     */
  52. /*   "######" can be any character valid for the UNIX file system.   */
  53. /*   Note, however, that the routine has to be generic to allow for  */
  54. /*   other file names to be placed in the spool directory without    */
  55. /*   collisions.                                                     */
  56. /*                                                                   */
  57. /*   Avoiding collisions in the spool directory is important; when   */
  58. /*   receiving files with mixed case names longer than 11            */
  59. /*   characters, sooner or later a file name collision will occur.   */
  60. /*                                                                   */
  61. /*   We can also assume that only UUPC will see these names, which   */
  62. /*   means we can transform the name using any method we choose, so  */
  63. /*   long as the UUPC functions opening the file always call         */
  64. /*   importpath, and that importpath is reducible (that is, two      */
  65. /*   calls to importpath with the same argument always yield the     */
  66. /*   same result).  Note that if end user really wanted the file in  */
  67. /*   the spool directory, all he has to do is rename the file-- far  */
  68. /*   better than losing the data because duplicate file names.       */
  69. /*                                                                   */
  70. /*   For these files, we map the name as follows:                    */
  71. /*                                                                   */
  72. /*   0 - If the name is a valid MS-DOS name, use it without changing */
  73. /*                                                                   */
  74. /*   1 - Begin the output name by inserting up to the first eight    */
  75. /*       characters of the remote host name (followed by a slash) as */
  76. /*       a subdirectory name.                                        */
  77. /*                                                                   */
  78. /*   2 - If the input name begins with an uppercase alphabetic       */
  79. /*       character followed by a period, also insert the alphabetic  */
  80. /*       (followed by a slash) to make this a second subdirectory.   */
  81. /*       Then, move the logical start of the input name past the two */
  82. /*       characters.                                                 */
  83. /*                                                                   */
  84. /*   3 - Determine the number of characters the local host and       */
  85. /*       remote hosts have equal to the next characters of the input */
  86. /*       name, up to a maximum of 8, and zero the lower of the two   */
  87. /*       counts.  Then, step past the number of characters of the    */
  88. /*       larger count.                                               */
  89. /*                                                                   */
  90. /*       For example, if the file name is X.keane22222 and the local */
  91. /*       host name is kendra (2 characters match) and the remote     */
  92. /*       host is keane1 (5 characters match), zero the number of     */
  93. /*       characters matched by kendra, and make the new start of the */
  94. /*       file name five characters further (at the first "2").       */
  95. /*                                                                   */
  96. /*   4 - Convert the remaining string using a base conversion, with  */
  97. /*       the input character size being from ascii "#" to ascii "z"  */
  98. /*       (88 characters) to the allowed set of characters in MS-DOS  */
  99. /*       file names (charset, below, 52 characters).                 */
  100. /*                                                                   */
  101. /*   5 - Prepend to the string to be converted the length of the     */
  102. /*       remote host added to the length of the local host           */
  103. /*       multiplied by 8 (both lengths were computed in step 3,      */
  104. /*       above).  The base conversion is also applied to this        */
  105. /*       "character", we which know will be in the range 1-64.       */
  106. /*                                                                   */
  107. /*   6 - If the string created by steps 4 and 5 exceeds 8            */
  108. /*       characters, insert a period after the eighth character to   */
  109. /*       make it a valid MS-DOS file name.  If the string created by */
  110. /*       steps 4 and 5 exceeds 11 characters, truncate the string by */
  111. /*       using the first eight and last three characters.            */
  112. /*                                                                   */
  113. /*   7 - Append the string created in steps 4 through 6 to the path  */
  114. /*       name created in steps 1 and 2.                              */
  115. /*                                                                   */
  116. /*   If the canonical name has a path, it is destined for an end     */
  117. /*   user, so we should not radically transform it like we do for    */
  118. /*   files in the spool directory.  Thus, if the canonical name has  */
  119. /*   a path, mung the canonical file name as follows:                */
  120. /*                                                                   */
  121. /*   1 - skip any path from the canonical name                       */
  122. /*                                                                   */
  123. /*   2 - copy up to 8 character from the canonical name converting . */
  124. /*       to _ and uppercase to lowercase.                            */
  125. /*                                                                   */
  126. /*   3 - if the name was longer than 8 character copy a . to the     */
  127. /*       host name and then copy the up to three characters from     */
  128. /*       the tail of the canonical name to the host name.            */
  129. /*                                                                   */
  130. /*   Note that this set of rules will cause a collision with names   */
  131. /*   that only differ in case, but leaves the name in a recongizable */
  132. /*   format for the user.                                            */
  133. /*-------------------------------------------------------------------*/
  134.  
  135.  
  136. void importpath(char *host, char const *canon, char const *remote)
  137. {
  138.    char *s, *out, c;
  139.    out = host;
  140.  
  141. /*--------------------------------------------------------------------*/
  142. /*                       Verify our parameters                        */
  143. /*--------------------------------------------------------------------*/
  144.  
  145.    if ( host == NULL )
  146.       panic();
  147.    if ( canon == NULL )
  148.       panic();
  149.    if ( remote == NULL )
  150.       panic();
  151.  
  152.  
  153. /*--------------------------------------------------------------------*/
  154. /*                      Define our character set                      */
  155. /*--------------------------------------------------------------------*/
  156.  
  157.     if ( E_charset == NULL )
  158.       E_charset = DOSCHARS;
  159.  
  160. /*--------------------------------------------------------------------*/
  161. /*                 Determine if spool file directory                  */
  162. /*--------------------------------------------------------------------*/
  163.  
  164.    if ((s = strrchr(canon, '/')) == (char *)NULL)
  165.    {                          /* File for spooling directory, use
  166.                                  internal character set to avoid
  167.                                  collisons                           */
  168.       static size_t range =  UNIX_END_C - UNIX_START_C + 1;
  169.                               /* Determine unique number characters in
  170.                                  the UNIX file names we are mapping  */
  171.       size_t charsetsize;     /* Number of allowed characters in
  172.                                  MS-DOS file names                   */
  173.  
  174.       size_t remlen = min(HOSTLEN, strlen(remote));
  175.                               /* Length of the remote name passed
  176.                                  in, shortened below to number of
  177.                                  characters matched in name          */
  178.       size_t nodelen = min(HOSTLEN, strlen(nodename));
  179.                               /* Length of the local host name,
  180.                                  shortened below to number of
  181.                                  characters matched in name          */
  182.       size_t subscript = 0;   /* Value of UNIX character to be
  183.                                  converted to MS-DOS character set   */
  184.       char *next        = host + remlen;
  185.       char tempname[FILENAME_MAX];
  186.       unsigned char number[MAX_DIGITS];
  187.                               /* Arbitary length number, for base
  188.                                  conversions                        */
  189.  
  190.       charsetsize = strlen( E_charset );
  191.  
  192. /*--------------------------------------------------------------------*/
  193. /*    Put the host name (up to six characters) at the beginning of    */
  194. /*    the MS-DOS file name as a sub-directory name.                   */
  195. /*--------------------------------------------------------------------*/
  196.  
  197.       strncpy(host, remote, remlen);
  198.       *next++ = '/';          /* Add in the sub-directory seperator  */
  199.       s = (char *) canon;     /* Get the beginnging of the UNIX name */
  200.  
  201. /*--------------------------------------------------------------------*/
  202. /*             If valid DOS name, use without translation             */
  203. /*--------------------------------------------------------------------*/
  204.  
  205.       if (ValidDOSName( canon ))
  206.       {
  207.          strcpy( next, canon );
  208.          return;
  209.       }
  210.  
  211. /*--------------------------------------------------------------------*/
  212. /*    Files in the spooling directory generally start with "D.",      */
  213. /*    "C.", or "X."; strip off any upper case letter followed by a    */
  214. /*    period into its own directory.                                  */
  215. /*--------------------------------------------------------------------*/
  216.  
  217.       if ((s[0] >= 'A') && (s[0] <= 'Z') && (s[1] == '.'))
  218.       {
  219.          *next++ = *s;        /* Copy the input character            */
  220.          *next++ = '/';       /* Add the sub-directory indicator too */
  221.          s += 2;              /* Step input string past the copied
  222.                                  data                                */
  223.       }
  224.  
  225.       while( remlen > 0 )
  226.       {
  227.          if (equaln(remote,s,remlen))
  228.             break;
  229.          remlen--;
  230.       }
  231.  
  232.       while( nodelen > 0 )
  233.       {
  234.          if (equaln(nodename,s,nodelen))
  235.             break;
  236.          nodelen--;
  237.       }
  238.  
  239.       if (nodelen > remlen )
  240.       {
  241.          remlen = 0;
  242.          s += nodelen;
  243.       }
  244.       else
  245.       {
  246.          nodelen = 0;
  247.          s += remlen;
  248.       }
  249.  
  250.       *next  = '\0';          /* Terminate first part of host string */
  251.  
  252. /*--------------------------------------------------------------------*/
  253. /*       Create a binary number which represents our file name        */
  254. /*--------------------------------------------------------------------*/
  255.  
  256.       for (subscript = 0; subscript < MAX_DIGITS; subscript++ )
  257.          number[subscript] = 0;  /* Initialize number to zero        */
  258.  
  259.       add(number, nodelen + remlen * HOSTLEN, MAX_DIGITS);
  260.                                  /* Append host name info to the
  261.                                     front of the converted string    */
  262.  
  263.       while( (*s != '\0') && (*number == '\0'))
  264.       {
  265.          mult(number, range, MAX_DIGITS); /* Shift the number over   */
  266.          add(number, *s++  - UNIX_START_C , MAX_DIGITS);
  267.                                           /* Add in new low order    */
  268.       } /* while */
  269.  
  270. /*-------------------------------------------------------------------*/
  271. /*   We now have stripped off the leading x. and host name, if any;  */
  272. /*   now, convert the remaining characters in the name by doing a    */
  273. /*   range to charset base conversion.                               */
  274. /*-------------------------------------------------------------------*/
  275.  
  276.       out = &tempname[FILENAME_MAX];
  277.       *--out = '\0';          /* Terminate the string we will build  */
  278.  
  279. /*--------------------------------------------------------------------*/
  280. /*         Here's the loop to actually do the base conversion         */
  281. /*--------------------------------------------------------------------*/
  282.  
  283.       while(adiv( number, charsetsize, &subscript, MAX_DIGITS))
  284.             *--out = E_charset[ subscript ];
  285.  
  286. /*--------------------------------------------------------------------*/
  287. /*    The conversion is done; now squeeze it into an 11 character     */
  288. /*    MS-DOS name with period.                                        */
  289. /*--------------------------------------------------------------------*/
  290.  
  291.       if (strlen(out) < 9)    /* Need extension inserted?            */
  292.          strcpy( next, out ); /* Length is ok, just copy it          */
  293.       else if (strlen(out) < 12)
  294.                               /* Need to truncate the final name?    */
  295.          sprintf( next , "%.8s.%s",out,&out[8]);   /* No --> format  */
  296.       else
  297.       {                       /* Yes --> Do so                       */
  298.          printmsg(1,"importpath: Truncated name \"%s\"",out);
  299.          sprintf( next,"%.8s.%s",out, &tempname[ FILENAME_MAX - 4 ] );
  300.       }
  301.    }
  302.    else {         /* Not file for spooling directory, convert it  */
  303.  
  304.       char *best_period;      /* ptr to last period in canonical fname */
  305.       char *in;
  306.       size_t column;
  307.  
  308.       s++;                    /* Step past slash in the name (/)     */
  309.  
  310. /*--------------------------------------------------------------------*/
  311. /*                 If a valid DOS name, use it as-is                  */
  312. /*--------------------------------------------------------------------*/
  313.  
  314.       if (ValidDOSName( s ))
  315.       {
  316.          strcpy( host, canon );
  317.          return;
  318.       }
  319.  
  320. /*--------------------------------------------------------------------*/
  321. /*                        Copy the input path                         */
  322. /*--------------------------------------------------------------------*/
  323.  
  324.       out = host;
  325.       in = (char *) canon;
  326.       while ( in < s)
  327.          *out++ = *in++;
  328.  
  329. /*--------------------------------------------------------------------*/
  330. /*    If the dataset name has a period, use it.  The rule we          */
  331. /*    follow is use the last period in the second through ninth       */
  332. /*    characters, otherwise use the last period in the dataset        */
  333. /*    name with the exception of leading period.                      */
  334. /*                                                                    */
  335. /*    In any case, we only copy up to eight characters for the        */
  336. /*    dataset name and up to three characters for the extension.      */
  337. /*--------------------------------------------------------------------*/
  338.  
  339.       best_period = NULL;     /* Assume no prince charming           */
  340.       for ( column = 1; (s[column] != '\0') && (column < 9); column++)
  341.          if ( s[column] == '.')
  342.             best_period = &s[column];
  343.  
  344.       if ( best_period == NULL )
  345.          best_period = strrchr(s+1 , '.');
  346.  
  347.       if ( best_period == NULL )
  348.          best_period = &s[ strlen( s ) ];
  349.  
  350.       column = 0;
  351.  
  352.       for (;; )
  353.       {
  354.          c = s[column++];
  355.          if ( (strchr( E_charset, c ) != NULL ) || (s == best_period))
  356.             *out++ = c;
  357.          else
  358.             *out++ = '_';
  359.  
  360.          if (  s[column] == '\0' )
  361.             break;
  362.  
  363.          if ((&s[column] == best_period) ||
  364.              (( best_period > s ) && (column > 7)))
  365.          {
  366.             if ((&s[column] != best_period))
  367.                printmsg(1,"importpath: Truncated name \"%s\" to 8 \
  368. characters",
  369.                         s);
  370.             s = best_period;
  371.             column = 0;
  372.          }
  373.          else if (( best_period == s ) && (column > 3))
  374.          {
  375.            printmsg(1,"importpath: Truncated extension \"%s\" to 3 \
  376. characters",
  377.                         s);
  378.             break;
  379.          }
  380.       } /* while */
  381.       *out++ = '\0';
  382.  
  383.    } /*else */
  384. } /*importpath*/
  385.  
  386.  
  387. /*--------------------------------------------------------------------*/
  388. /*    V a l i d D O S N a m e                                         */
  389. /*                                                                    */
  390. /*    Validate an MS-DOS file name                                    */
  391. /*--------------------------------------------------------------------*/
  392.  
  393. static boolean ValidDOSName( const char *s)
  394. {
  395.    char *ptr;
  396.    size_t len = strlen ( s );
  397.    char tempname[FILENAME_MAX];
  398.  
  399.    strcpy( tempname, s);
  400.  
  401. /*--------------------------------------------------------------------*/
  402. /*                 Name must be 12 characters or less                 */
  403. /*--------------------------------------------------------------------*/
  404.  
  405.    if (len > 12)
  406.       return FALSE;
  407.  
  408. /*--------------------------------------------------------------------*/
  409. /*    Simple file name without extension must be eight chracters      */
  410. /*    or less                                                         */
  411. /*--------------------------------------------------------------------*/
  412.  
  413.    ptr = strrchr(tempname, '.');
  414.    if ((ptr == NULL) && (len > 8))
  415.       return FALSE;
  416.  
  417. /*--------------------------------------------------------------------*/
  418. /*          Period must be in second through ninth character          */
  419. /*--------------------------------------------------------------------*/
  420.  
  421.    if ((ptr == tempname) || (ptr > &tempname[8]))
  422.       return FALSE;
  423.  
  424. /*--------------------------------------------------------------------*/
  425. /*             Extension must be three characters or less             */
  426. /*--------------------------------------------------------------------*/
  427.  
  428.    if ( strlen( ptr ) > 4 )   /* Three characters plus the period?   */
  429.       return FALSE;           /* No --> Too much                     */
  430.  
  431. /*--------------------------------------------------------------------*/
  432. /*                          Only one period                           */
  433. /*--------------------------------------------------------------------*/
  434.  
  435.    if (ptr != strchr(tempname, '.'))
  436.       return FALSE;
  437.  
  438. /*--------------------------------------------------------------------*/
  439. /*                Must only be valid MS-DOS characters                */
  440. /*--------------------------------------------------------------------*/
  441.  
  442.    strlwr( tempname );        /* Map into our desired character set  */
  443.    if ( ptr != NULL )
  444.       *ptr = 'x';             /* We've already accounted for the
  445.                                  period, don't let it ruin our day   */
  446.  
  447.    if (strspn(tempname, E_charset ) == len)
  448.    {
  449.       printmsg(4,"ValidDOSName: \"%s\" is valid", s);
  450.       return TRUE;
  451.    }
  452.    else
  453.       return FALSE;
  454.  
  455. } /* ValidateDOSName */
  456.